unit uNetworkDriver;

interface

uses Dialogs, Forms, ScktComp, Sysutils, Windows, uBusMessage, uBusDriver;

type

  TNetworkDriver = class (TBusDriver)
    private
      aSocket: TClientSocket;
      aConnected: boolean;

    public
      constructor Create(paAddress: string; paPort: Cardinal);

      function Connect: Boolean; override;
      function Disconnect: Boolean; override;
      function IsConnected: Boolean; override;

      function SendMessageAndGetAnswer(var paMessage: TBusMessage): Boolean; override;

      procedure OnConnect(sender: TObject; scktComp: TCustomWinSocket);
      procedure OnError(Sender: TObject; Socket: TCustomWinSocket;
                        ErrorEvent: TErrorEvent; var ErrorCode: Integer);
      procedure OnDisconnect(sender: TObject; scktComp: TCustomWinSocket);
  end;

implementation

{ TNetworkDriver }

function TNetworkDriver.Connect: Boolean;
begin
  try
    aSocket.Open;
    aSocket.Active := true;
    result := true;
  except
    result := false;
  end;
end;

constructor TNetworkDriver.Create(paAddress: string; paPort: Cardinal);
begin
  aSocket := TClientSocket.Create(nil);
  aSocket.ClientType := ctBlocking;
  aSocket.Address := paAddress;
  aSocket.Port := paPort;
  aSocket.OnConnect := OnConnect;
  aSocket.OnError := OnError;
  aSocket.OnDisconnect := OnDisconnect;

  aConnected := false;
end;

function TNetworkDriver.Disconnect: Boolean;
begin
  aSocket.Active := false;
  aSocket.Close;

  result := true;
end;

function TNetworkDriver.IsConnected: Boolean;
begin
  result := aConnected;
end;

function TNetworkDriver.SendMessageAndGetAnswer(var paMessage: TBusMessage): Boolean;
var
  ssTemp: TWinSocketStream;
  strResponse: AnsiString;

begin
  if not aConnected then
    exit;

  try
    ssTemp := TWinSocketStream.Create(aSocket.Socket, 10000);
    aSocket.Socket.SendText(paMessage.ToString);
    ssTemp.WaitForData(10000);
    strResponse := aSocket.Socket.ReceiveText;
  finally
    ssTemp.Free;
  end;

  paMessage.FromString(strResponse);
  result := true;
end;

procedure TNetworkDriver.OnConnect(sender: TObject; scktComp: TCustomWinSocket);
begin
  aConnected := true;
end;

procedure TNetworkDriver.OnError(Sender: TObject; Socket: TCustomWinSocket;
                                 ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  aConnected := false;
  if ErrorCode = 10054 then
    ShowMessage('Disconnected from track.')
  else
    ShowMessage('Connection error: ' + SysErrorMessage(ErrorCode));
  ErrorCode := 0;
end;

procedure TNetworkDriver.OnDisconnect(sender: TObject; scktComp: TCustomWinSocket);
begin
  if aConnected then
  begin
    ShowMessage('Disconnected from track.');
    aConnected := false;
    aSocket.Close;
  end;
end;

end.